perm filename MGRAPH.PUB[HAL,HE]2 blob
sn#129805 filedate 1974-11-14 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00002 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 .gph:NEWSS GRAPH STRUCTURES
C00010 ENDMK
C⊗;
.gph:NEWSS GRAPH STRUCTURES
Affixments are stored in both the compiler and the runtime by means of a
graph structure. The nature of this structure is described
in {sssref rgf}.
Suffice it here to say that if the value
of a variable is needed, and that value is marked as invalid, then
the list of calculator expressions for that variable is searched for
one which can compute a valid value; if none of the calculators will
work
(for example, they all depend themselves on invalid values),
then the current (invalid) value is returned as the best answer
available. When a new value is assigned to a variable, all those
values whose calculators depend on the new value are marked as
invalid, so that the next time they are needed, graph searching is
performed. Building a graph structure therefore involves specifying
the calculators for all variables. Usually, this will be be done
implicitly by means of the AFFIX
and UNFIX primitives. However, 'AL also supplies primitives for explicit
manipulation of graph structure. The principal explicit means
employed for this purpose is the %4graph assignment statement%*:
.UNFILL
<variable> <= <expression>
.REFILL
where "<=" may be read "is computed by". This construct causes
<expression> to be added to the list of calculators for <variable>.
Similarly,
.UNFILL
<variable> <≠ <expression>
.REFILL
causes <expression> to be removed from the list of calculators, and
.UNFILL
<variable> <<= <expression>
.REFILL
replaces the current calculator list for <expression>. The statement
.UNFILL
<variable> <<= ;
.REFILL
would cause the calculator list to be set to null.
It is frequently very inconvenient to retype an entire expression in
order to remove it from the calculator list. 'AL allows the user to
attach a name to an expression in a graph assignment statement by use
of the construct
.UNFILL
<variable> <= "id" <expression>
.REFILL
Then the construct
.UNFILL
<variable> <≠ "id"
.REFILL
will remove the named expression from the calculator list. For
instance,
.UNFILL
F1 <= "foo" T*F2;
:
F1 <≠ "foo";
.REFILL
would have the same effect as
.UNFILL
F1 <= T*F2;
:
F1 <≠ T*F2;
.REFILL
In addition to the calculator list, a list of %4updater%* routines is
associated with every variable. These routines are executed whenever
the variable value is changed. Initially, the list of updaters is
empty. However, the construct
.UNFILL
WHEN CHANGING <variable> ALSO DO <label>: <statement>;
.REFILL
will cause <statement> to be added to the list of updaters for
<variable>. (the label is optional, but is necessary if the <statement>
is ever to be removed from the updater list.) In <statement>, the
reserved words OLD and NEW may be used to refer to the old and new
values of var, respectively. For instance:
.UNFILL
WHEN CHANGING f2 ALSO DO foo: f1 ← NEW*(OLD → F1);
.REFILL
Updaters may be removed from the updater list by the statement
.UNFILL
WHEN CHANGING <variable> DONT DO <label>
.REFILL
For our above example, this would be
.UNFILL
WHEN CHANGING f2 DONT DO foo;
.REFILL
The form
.UNFILL
WHEN CHANGING <variable> ONLY DO <statement>;
.REFILL
replaces the updater list with one containing just <statement>, and
.UNFILL
WHEN CHANGING <variable> ONLY DO ;
.REFILL
clears the updater list completely. Since the affix structure makes
use of updater and calculator lists (see {sssref rgf}), careless use of the
replacement form is not advised.
One possible use for updater routines is tracing. For example,
.UNFILL
WHEN CHANGING v ALSO DO
WRITE("The value of V is now ",NEW);
.REFILL
Details of the graph structure algorithms may be found in the appendix
on runtime routines.
One additional point that should be mentioned here is that the
updater routines for a variable are %4not%* called if the variable's
value is modified as a side effect of a change to some variable in
one of its calculators.
.gat: NEWSSS CONCERNING AFFIX AND UNFIX
The AFFIX and UNFIX statements are defined by their effects on the
graph structures.
.UNFILL
AFFIX f1 TO f2 BY t1
.UNFILL
is equivalent to
.REFILL
t1 ← f2 → f1;
f1 <= "xxx" t1 * f2;
WHEN CHANGING f1 ALSO DO "yyy" t1 ← (f2 → NEW);
ASSERT FACT(AFFIXED, f1, f2, t1);
.REFILL
Then,
.UNFILL
UNFIX f1 FROM f2;
.REFILL
is equivalent to
.UNFILL
f1 <≠ "xxx";
WHEN CHANGING f1 DONT DO yyy;
DENY FACT(AFFIXED, f1, f2, ANYTHING);
ASSERT FACT(WAS_AFFIXED, f1, f2);
.REFILL
Similarly,
.UNFILL
AFFIX f1 TO f2 BY t1 RIGIDLY
.REFILL
is equivalent to
.UNFILL
t1 ← f2 → f1;
f1 <= t1 * f2;
f2 <= INVERSE(t1) * f1 .
.REFILL